-
Notifications
You must be signed in to change notification settings - Fork 0
Lastuse proofread #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
I didnt do the |
| List(new InstrumentCoverage) :: // Perform instrumentation for code coverage (if -coverage-out is set) | ||
| List(new CrossVersionChecks, // Check issues related to deprecated and experimental | ||
| new FirstTransform, // Some transformations to put trees into a canonical form | ||
| new VerifyLastUseAnnotations, // Well actually it has its own tree traverser, so it does not make that much sense to be here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: You should usually add new phases at the end of the mega phase list
|
|
||
| object VerifyLastUseAnnotations: | ||
| val name: String = "verifyLastUseAnnotations" | ||
| val description: String = "verify that @lastUse annotations are use correctly" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| val description: String = "verify that @lastUse annotations are use correctly" | |
| val description: String = "verify that @lastUse annotations are used correctly" |
| val name: String = "verifyLastUseAnnotations" | ||
| val description: String = "verify that @lastUse annotations are use correctly" | ||
|
|
||
| case class VariableStatus(allowVar: Boolean, allowAnnot: Boolean, isAfterValDef: Boolean /*find better name*/){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Could these fields be expressed in terms of the "state/status" of the variable, instead of actions that are allowed? e.g. (wasDeclared, wasNullified, etc.)
IMHO the cleanest way is for fields to mean "state" and for methods to mean "capability to do an action".
| //TODO find a better name | ||
| type VariableStatusMap = Map[Symbol, VariableStatus] | ||
|
|
||
| extension(ss: VariableStatusMap) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit(personal preference): conventionally, we usually make a space after a keyword (here extension)
Coincidentally, GH syntax highlighting breaks because of that here.
| /* | ||
| Verifies the use of the @lastUse annotation | ||
| following rules are applied: | ||
| 1. the variable cannot be reused after being annotated | ||
| 2. the variable cannot be annotated in a loop (or in a lambda) TODO modify | ||
| 3. exclusive branches (if-else, match cases) do not impact each other. | ||
| the implementation goes as follows (considering nested functions): | ||
| we follow all variables with a @lastUse annotation | ||
| PrepareForDefDef: the miniphase dives in the deepest method in the tree, storing in context the lastUse variable from enclosing methods ("captured") | ||
| transformDefDef: each method (children first) are verified. If it contains a lastUse captured variable, it is marked as such (in "capturedVariables") | ||
| this allows illegal function calls to be detected, but all function definitions stay legal. | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: You should use the doc comment syntax – /** */. link: https://docs.scala-lang.org/style/scaladoc.html
|
|
||
|
|
||
| override def prepareForDefDef(tree: DefDef)(using Context): Context = | ||
| val freeVars = ctx.property(lastUseVariables).getOrElse(Set.empty[Symbol]) ++ tree.getAttachment(methodLastUses).getOrElse(Set.empty[Symbol]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: are those actually free variables? Isn't it just the set of all lastUse variables?
| the implementation goes as follows (considering nested functions): | ||
| we follow all variables with a @lastUse annotation | ||
| PrepareForDefDef: the miniphase dives in the deepest method in the tree, storing in context the lastUse variable from enclosing methods ("captured") | ||
| transformDefDef: each method (children first) are verified. If it contains a lastUse captured variable, it is marked as such (in "capturedVariables") | ||
| this allows illegal function calls to be detected, but all function definitions stay legal. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: You probably shouldn't include implementation details in doc comments.
| private val lastUseVariables = Property.Key[Set[Symbol]] | ||
| private val capturedVariables = mutable.Map.empty[Symbol, Set[Symbol]] //method => lastUse symbols from outside it is using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Can we change the naming, so that the meaning of all the keys and maps is more clear?
Also is my intuition/understanding correct that? That:
lastUseVariables=all lastUse variables in scopecapturedVariables=for a given method -> captured lastUse variablesmethodLastUses=for a given method -> variables lastUsed in its body- plus concaptually, we also use the set of lastUse variables defined in this method
|
|
||
| if (tree.tpe.typeSymbol.isPrimitiveValueClass || tree.symbol.is(Flags.Method)) | ||
| report.error("`@lastUse` annotation cannot be used on primitives and methods", tree.sourcePos) | ||
| if tree.symbol.owner != method.symbol && !tree.isInstanceOf[This] then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Will this break for nested variables? Don't we conceptually also want enclosingMethod here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: You really seem to like line breaks ^^
No description provided.